package org.zxyj.core.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.zxyj.core.dao.IBaseDao;
import org.zxyj.core.entity.BaseEntity;
import org.zxyj.core.entity.Pagination;
import org.zxyj.core.errorno.SystemErrorNo;
import org.zxyj.core.exception.ServiceException;

/**
 * @author zhaoyong
 * @version 2016年2月19日
 */
public abstract class AbstractBaseServiceImpl<Dao extends IBaseDao<T>, T extends BaseEntity<T>>
		implements IBaseService<T> {

	protected Logger logger = LoggerFactory.getLogger(this.getClass());

	/**
	 * 持久层对象
	 */
	@Autowired
	protected Dao dao;

	public List<T> listEntities(Map<String, Object> criteria) {
		logger.debug("listing entities refer to criteria, param: [{}]", criteria);

		if (null == criteria) {
			criteria = new HashMap<String, Object>();
		}
		return dao.find(criteria);
	}

	public Pagination listEntities(Map<String, Object> criteria, Pagination pagination) {
		logger.debug("listing entities refer to criteria and pagination, param: criteria[{}], pagination[{}]", criteria,
				pagination);
		if (null == criteria) {
			criteria = new HashMap<String, Object>();
		}
		criteria.put("pagination", pagination);
		List<T> entities = dao.find(criteria);
		Long totalCount = dao.count(criteria);
		if (null == pagination) {
			pagination = new Pagination();
		}
		pagination.setTotal(totalCount);
		pagination.setDatas(entities);

		return pagination;
	}

	public T findEntity(Map<String, Object> criteria) {
		logger.debug("find entity refer to criteria, param: criteria[{}]", criteria);

		if (null == criteria) {
			// 参数错误
			return null;
		}

		List<T> entities = dao.find(criteria);
		if (!CollectionUtils.isEmpty(entities)) {
			return entities.get(0);
		}
		return null;
	}

	@Transactional(rollbackFor = Exception.class)
	public void persistentEntity(T entity) {
		logger.debug("persistenting entity to DB, param: entity[{}]", entity);

		// 参数校验
		if (null == entity) {
			logger.warn("persistenting entity to DB, param entity is null.");
			throw new ServiceException(SystemErrorNo.PARAMETER_IS_NULL);
		}

		if (null == entity.getId()) {
			entity.setCreateTime(new Date());
			dao.insert(entity);
			logger.debug("entity not exist in DB, then save new entity to DB, entity: {}", entity.getId());
		} else {
			Map<String, Object> criteria = new HashMap<String, Object>();
			criteria.put("id", entity.getId());
			T tempEntity = this.findEntity(criteria);
			if (null == tempEntity) {
				entity.setCreateTime(new Date());
				dao.insert(entity);
				logger.debug("entity not exist in DB, then save new entity to DB, entity: {}", entity.getId());
			} else {
				entity.setUpdateTime(new Date());
				dao.update(entity);
				logger.debug("entity exist in DB, then update entity info, entity: {}", entity.getId());
			}
		}
	}

	@Transactional(rollbackFor = Exception.class)
	public void deleteEntity(Map<String, Object> criteria) {
		logger.debug("deleting entity from DB, param: criteria[{}]", criteria);

		if (!MapUtils.isEmpty(criteria)) {
			dao.delete(criteria);
		}
	}
}